﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace NFramework.DataAccess
{
    public abstract class CommandParameterCollection : ICommandParameterCollection
	{

        public static CommandParameterCollection CreateCollection(System.Data.Common.DbParameterCollection parameters)
        {
            if (parameters.GetType().Equals(typeof(SqlParameterCollection)))
            {
                return new SqlCommandParameterCollection(parameters);
            }
            else
            {
                return new OdbcCommandParameterCollection(parameters);
            }
        }

        public CommandParameterCollection(System.Data.Common.DbParameterCollection parameters)
        {
            _parameters.Instance = parameters;
        }

        protected virtual IDataParameterCollection Parameters
        {
            get { return _parameters.Instance;  }
        }
        private ObjectModel.AutoInstance<IDataParameterCollection, DataParameterCollection> _parameters;

        #region [ ICommandParameterCollection Members ]

        public T GetOutput<T>(string name, T defaultValue)
        {
            IDbDataParameter param = Parameters[name] as IDbDataParameter;

            if (param.Value != null)
            {
                return (T)param.Value;
            } else {
                return defaultValue;
            }
        }

        public abstract System.Data.IDbDataParameter Add(string name, System.Data.DbType dbType);

        public System.Data.IDbDataParameter this[string parameterName]
        {
            get
            {
                return new CommandParameter(Parameters[parameterName] as IDbDataParameter);
            }
            set
            {
                Parameters[parameterName] = value;
            }
        }

        public System.Data.IDbDataParameter this[int index]
        {
            get
            {
                return new CommandParameter(Parameters[index] as IDbDataParameter);
            }
            set
            {
                Parameters[index] = value;
            }
        }

        public bool Contains(int parameterIndex)
        {
            return 0 <= parameterIndex && parameterIndex < Parameters.Count;
        }

        #endregion

        #region [ IDataParameterCollection Members ]

        public bool Contains(string parameterName)
        {
            return Parameters.Contains(parameterName);
        }

        public int IndexOf(string parameterName)
        {
            return Parameters.IndexOf(parameterName);
        }

        public void RemoveAt(string parameterName)
        {
            Parameters.RemoveAt(parameterName);
        }

        object System.Data.IDataParameterCollection.this[string parameterName]
        {
            get
            {
                return Parameters[parameterName];
            }
            set
            {
                Parameters[parameterName] = value;
            }
        }

        #endregion

        #region [ IList Members ]

        public int Add(object value)
        {
            return Parameters.Add(value);
        }

        public void Clear()
        {
            Parameters.Clear();
        }

        public bool Contains(object value)
        {
            return Parameters.Contains(value);
        }

        public int IndexOf(object value)
        {
            return Parameters.IndexOf(value);
        }

        public void Insert(int index, object value)
        {
            Parameters.Insert(index, value);
        }

        public bool IsFixedSize
        {
            get { return Parameters.IsFixedSize; }
        }

        public bool IsReadOnly
        {
            get { return Parameters.IsReadOnly; }
        }

        public void Remove(object value)
        {
            Parameters.Remove(value);
        }

        public void RemoveAt(int index)
        {
            Parameters.RemoveAt(index);
        }

        object System.Collections.IList.this[int index]
        {
            get
            {
                return Parameters[index];
            }
            set
            {
                Parameters[index] = value;
            }
        }

        #endregion

        #region [ ICollection Members ]

        public void CopyTo(Array array, int index)
        {
            Parameters.CopyTo(array, index);
        }

        public int Count
        {
            get { return Parameters.Count; }
        }

        public bool IsSynchronized
        {
            get { return Parameters.IsSynchronized; }
        }

        public object SyncRoot
        {
            get { return Parameters.SyncRoot; }
        }

        #endregion

        #region [ IEnumerable Members ]

        public System.Collections.IEnumerator GetEnumerator()
        {
            return Parameters.GetEnumerator();
        }

        #endregion

        #region [ IList<IDbDataParameter> Members ]

        public int IndexOf(IDbDataParameter item)
        {
            return Parameters.IndexOf(item);
        }

        public void Insert(int index, IDbDataParameter item)
        {
            Parameters.Insert(index, item);
        }

        #endregion

        #region [ ICollection<IDbDataParameter> Members ]

        public void Add(IDbDataParameter item)
        {
            Parameters.Add(item);
        }

        public bool Contains(IDbDataParameter item)
        {
            return Parameters.Contains(item);
        }

        public void CopyTo(IDbDataParameter[] array, int arrayIndex)
        {
            Parameters.CopyTo(array, arrayIndex);
        }

        public bool Remove(IDbDataParameter item)
        {
            Parameters.Remove(item);
            return false;
        }

        #endregion

        #region [ IEnumerable<IDbDataParameter> Members ]

        IEnumerator<IDbDataParameter> IEnumerable<IDbDataParameter>.GetEnumerator()
        {
            return Parameters.GetEnumerator() as IEnumerator<IDbDataParameter>;
        }

        #endregion
    }

    class SqlCommandParameterCollection : CommandParameterCollection
    {
        public SqlCommandParameterCollection(System.Data.Common.DbParameterCollection parameters) : base(parameters) {}

        public override IDbDataParameter Add(string name, DbType dbType)
        {
            IDbDataParameter added = new SqlParameter(name, dbType);
            Parameters.Add(added);
            return added;
        }
    }

    class OdbcCommandParameterCollection : CommandParameterCollection
    {
        public OdbcCommandParameterCollection(System.Data.Common.DbParameterCollection parameters) : base(parameters) { }

        public override IDbDataParameter Add(string name, DbType dbType)
        {
            IDbDataParameter added = new System.Data.Odbc.OdbcParameter(name, dbType);
            Parameters.Add(added);
            return added;
        }
    }
}
